# -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from openerp.osv import fields, osv
from openerp.tools.translate import _
from openerp import netsvc
from openerp.tools import float_round, float_is_zero, float_compare
import openerp.addons.decimal_precision as dp

class account_voucher(osv.osv):

    _inherit = 'account.voucher'
    
    def _get_writeoff_amount(self, cr, uid, ids, name, args, context=None):
        if not ids: return {}
        currency_obj = self.pool.get('res.currency')
        res = {}
        for voucher in self.browse(cr, uid, ids, context=context):
            res[voucher.id] =  float_round(voucher.amount - voucher.total_payment_amount,2)
        return res
     
    def _get_pay_amount(self, cr, uid, ids, name, args, context=None):
        if not ids: return {}
        res_partner_obj = self.pool.get('res.partner')
        res = {}
        alloc_inv_amt_debit = 0.00
        alloc_inv_home_debit = 0.00

        for voucher in self.browse(cr, uid, ids, context=context):
            if voucher.type in ('purchase', 'payment'):
                for lines in voucher.line_dr_ids:
                    if lines.amount > 0:
                        alloc_inv_amt_debit += lines.amount or 0.00
            else:
                for lines in voucher.line_cr_ids:    
                    if lines.amount > 0:
                        alloc_inv_amt_debit += lines.amount or 0.00
            
            res[voucher.id] = alloc_inv_amt_debit

        return res
    
    def _total_in_home_currency(self, cr, uid, ids, name, args, context=None):
        if not ids: return {}
        res = {}
        for voucher in self.browse(cr, uid, ids, context=context):
            company_currency = voucher.company_id.currency_id
            voucher_currency = voucher.journal_id.currency or company_currency
            if voucher_currency.id == company_currency.id:
                res[voucher.id] = voucher.amount
            else:
                ctx = {'date':voucher.date}
                voucher_rate = ((voucher.change_rate > 0) and voucher.change_rate) or voucher.ex_rate
                company_rate = self.pool.get('res.currency').browse(cr, uid, company_currency.id, context=ctx).rate
                res[voucher.id] = self._rounding_voucher(cr, uid, voucher.amount / voucher_rate * company_rate, voucher_currency.rounding, self.pool.get('decimal.precision').precision_get(cr, uid, 'Account'))
                
        return res
    
    def cancel_voucher(self, cr, uid, ids, context=None):
        reconcile_pool = self.pool.get('account.move.reconcile')
        move_pool = self.pool.get('account.move')
        move_line_pool = self.pool.get('account.move.line')
        for voucher in self.browse(cr, uid, ids, context=context):
            # refresh to make sure you don't unlink an already removed move
            voucher.refresh()
            for line in voucher.move_ids:
                # refresh to make sure you don't unreconcile an already unreconciled entry
                line.refresh()
                if line.reconcile_id:
                    if line.is_depo_main:
                        raise osv.except_osv(_('Error'), _("cannot un-reconcile unless un-reconcile first the related deposit transaction."))
                    move_lines = [move_line.id for move_line in line.reconcile_id.line_id]
                    move_lines.remove(line.id)
                    reconcile_pool.unlink(cr, uid, [line.reconcile_id.id])
                    if len(move_lines) >= 2:
                        move_line_pool.reconcile_partial(cr, uid, move_lines, 'auto',context=context)
                if line.reconcile_partial_id:
                    if line.is_depo_main:
                        raise osv.except_osv(_('Error'), _("cannot un-reconcile unless un-reconcile first the related deposit transaction."))
            if voucher.move_id:
                move_pool.button_cancel(cr, uid, [voucher.move_id.id])
                move_pool.unlink(cr, uid, [voucher.move_id.id])
        res = {
            'state':'cancel',
            'move_id':False,
        }
        self.write(cr, uid, ids, res)
        return True

    def _rounding_voucher(self, cr, uid, total_amount, voucher_currency_rounding, decimal_prec_acc, context=None):
        total_amount = float_round(total_amount, precision_rounding=voucher_currency_rounding)
        total_amount = round(total_amount,decimal_prec_acc)

        return total_amount

    def onchange_date(self, cr, uid, ids, partner_id, journal_id, ttype, currency, line_dr_ids, line_cr_ids, context=None):

        default = self.onchange_journal2(cr, uid, ids, partner_id, journal_id, ttype, currency, line_dr_ids, line_cr_ids, context)
        if line_dr_ids[0][2] or line_cr_ids[0][2]:
            if 'warning' in default:
                if 'message' in default['warning']:
                    mess = default['warning']['message']
                    default['warning'].update({'message': _( mess + '\n & \n' +'you have change the date, the system will clearing the data, please use compute button to recompute again!')})
                else:
                    default['warning'].update({'message': _('you have change the date, the system will clearing the data, please use compute button to recompute again!')})
            else:
                default['warning'] = {'title': _('Warning'), 'message': _('you have change the date, the system will clearing the data, please use compute button to recompute again!')}
            
            if 'line_dr_ids' in default['value']:
                default['value'].update({'line_dr_ids': []})
            else:
                default['value']['line_dr_ids'] = []
            
            if 'line_cr_ids' in default['value']:
                default['value'].update({'line_cr_ids': []})
            else:
                default['value']['line_cr_ids'] = []

        return default

    def onchange_change_rate(self, cr, uid, ids, partner_id, journal_id, ttype, currency, line_dr_ids, line_cr_ids, context=None):

        default = self.onchange_journal2(cr, uid, ids, partner_id, journal_id, ttype, currency, line_dr_ids, line_cr_ids, context)
        if line_dr_ids[0][2] or line_cr_ids[0][2]:
            if 'warning' in default:
                if 'message' in default['warning']:
                    mess = default['warning']['message']
                    default['warning'].update({'message': _( mess + '\n & \n' +'you have change the rate, the system will clearing the data, please use compute button to recompute again!')})
                else:
                    default['warning'].update({'message': _('you have change the rate, the system will clearing the data, please use compute button to recompute again!')})
            else:
                default['warning'] = {'title': _('Warning'), 'message': _('you have change the rate, the system will clearing the data, please use compute button to recompute again!')}
            
            if 'line_dr_ids' in default['value']:
                default['value'].update({'line_dr_ids': []})
            else:
                default['value']['line_dr_ids'] = []
            
            if 'line_cr_ids' in default['value']:
                default['value'].update({'line_cr_ids': []})
            else:
                default['value']['line_cr_ids'] = []

        return default

    def onchange_journal2(self, cr, uid, ids, partner_id, journal_id, ttype, currency, line_dr_ids, line_cr_ids, context=None):
        """price
        Returns a dict that contains new values and context

        @param partner_id: latest value from user input for field partner_id
        @param args: other arguments
        @param context: context arguments, like lang, time zone

        @return: Returns a dict which contains new values, and context
        """
        default = {
            'value':{},
        }

        if not journal_id:
            return False

        partner_pool = self.pool.get('res.partner')
        journal_pool = self.pool.get('account.journal')

        journal = journal_pool.browse(cr, uid, journal_id, context=context)
        partner = partner_id and partner_pool.browse(cr, uid, partner_id, context=context) or False
        account_id = False
        tr_type = False
        if journal.type in ('sale','sale_refund'):
            account_id = partner and partner.property_account_receivable.id or False
            tr_type = 'sale'
        elif journal.type in ('purchase', 'purchase_refund','expense'):
            account_id = partner and partner.property_account_payable.id or False
            tr_type = 'purchase'
        else:
            if not journal.default_credit_account_id or not journal.default_debit_account_id:
                raise osv.except_osv(_('Error !'), _('Please define default credit/debit accounts on the journal "%s" !') % (journal.name))
            account_id = journal.default_credit_account_id.id or journal.default_debit_account_id.id
            tr_type = 'receipt'
        if not account_id:
            if not journal.default_credit_account_id or not journal.default_debit_account_id:
                raise osv.except_osv(_('Error !'), _('Please define default credit/debit accounts on the journal "%s" !') % (journal.name))
            account_id = journal.default_credit_account_id.id or journal.default_debit_account_id.id
        currency_id = False
        if journal.currency:
            currency_id = journal.currency.id
        else:
            currency_id = journal.company_id.currency_id.id
        if currency:
            if currency != currency_id:
                default['value']['line_dr_ids'] = []
                default['value']['line_cr_ids'] = []
                if line_dr_ids[0][2] or line_cr_ids[0][2]:
                    if 'warning' in default:
                        if 'message' in default['warning']:
                            mess = default['warning']['message']
                            default['warning'].update({'message': _( mess + '\n & \n' +'you have selected different Currency, the system will clearing the data, please use compute button to recompute again!')})
                        else:
                            default['warning'].update({'message': _('you have selected different Currency, the system will clearing the data, please use compute button to recompute again!')})
                    else:
                        default['warning'] = {'title': _('Warning'), 'message': _('you have selected different Currency, the system will clearing the data, please use compute button to recompute again!')}
        default['value'].update({'currency_id': currency_id})
        default['value']['account_id'] = account_id
        default['value']['type'] = ttype or tr_type
        
        return default

    def unlink(self, cr, uid, ids, context=None):
        for t in self.read(cr, uid, ids, ['state'], context=context):
            if t['state'] not in ('draft'):
                raise osv.except_osv(_('Invalid Action!'), _('Cannot delete voucher(s) which are already opened or paid or cancel.'))
        return super(account_voucher, self).unlink(cr, uid, ids, context=context)

    def _get_grand_total(self, cr, uid, ids, name, args, context=None):
        if not ids: return {}
        currency_obj = self.pool.get('res.currency')
        res = {}
        for voucher in self.browse(cr, uid, ids, context=context):
            if voucher.type in ('purchase', 'payment'):
                res[voucher.id] =  voucher.amount + voucher.bank_charges_amount
            else:
                res[voucher.id] =  voucher.amount - voucher.bank_charges_amount
        return res

    def _rate(self, cr, uid, ids, name, arg, context=None):
        if not ids: return {}
        res = {}
        res_currency_rate_obj = self.pool.get("res.currency.rate")

        for obj in self.browse(cr, uid, ids, context=context):
            current_currency = self._get_current_currency(cr, uid, obj.id, context)
            cur_date = obj.date or False
            if current_currency and cur_date:
                res_currency_rate_ids = res_currency_rate_obj.search(cr, uid, [('currency_id', '=', current_currency), ('name', '<=', cur_date)], order='name DESC', limit=1)
                if res_currency_rate_ids:
                    res[obj.id] = res_currency_rate_obj.browse(cr, uid, res_currency_rate_ids[0], context=context).rate
                else:
                    res[obj.id] = 0
            else:
                res[obj.id] = 0
        return res

    def _convert_to_home_voucher(self, cr, uid, voucher, total_amount, context=None):
        amount = 0
        voucher_currency = voucher.journal_id.currency or voucher.company_id.currency_id
        voucher_rate = ((voucher.change_rate > 0) and voucher.change_rate) or voucher.ex_rate
        company_rate = self.pool.get('res.currency').browse(cr, uid, voucher.company_id.currency_id.id, context=context).rate
        amount = self._rounding_voucher(cr, uid, total_amount / voucher_rate * company_rate, voucher_currency.rounding, self.pool.get('decimal.precision').precision_get(cr, uid, 'Account'))
        return amount
        
    def _bank_charges_in_company_currency(self, cr, uid, ids, name, args, context=None):
        if not ids: return {}
        res = {}
        for voucher in self.browse(cr, uid, ids, context=context):
            company_currency =  voucher.company_id.currency_id
            voucher_currency = voucher.journal_id.currency or company_currency
            if voucher_currency.id == company_currency.id:
                res[voucher.id] = voucher.bank_charges_amount
            else:
                res[voucher.id] = self._convert_to_home_voucher(cr, uid, voucher, voucher.bank_charges_amount)

        return res

    def _paid_amount_in_company_currency(self, cr, uid, ids, name, args, context=None):
        if context is None:
            context = {}
        res = {}
        for v in self.browse(cr, uid, ids, context=context):
            res[v.id] = self._convert_to_home_voucher(cr, uid, v, v.amount)

        return res

    def onchange_pay_option(self, cr, uid, ids, payment_option, type, partner_id, context=None):
        if context is None:
            context = {}
        res = {}
        if (not payment_option) or (not partner_id):
            return res
        
        if payment_option == 'none':
            res['value']= {'writeoff_acc_id': False}

        if payment_option == 'without_writeoff':
            partner = self.pool.get('res.partner').browse(cr, uid, partner_id, context=context)
            if type == 'payment':
                res['value']= {'writeoff_acc_id': partner and partner.property_account_payable and partner.property_account_payable.id or False}
                res['domain'] = {'writeoff_acc_id': [('type','=','payable')]}
            elif type == 'receipt':
                res['value']= {'writeoff_acc_id': partner and partner.property_account_receivable and partner.property_account_receivable.id or False}
                res['domain'] = {'writeoff_acc_id': [('type','=','receivable')]}
        if payment_option == 'with_writeoff':
            res['value']= {'writeoff_acc_id': False}
            res['domain'] = {'writeoff_acc_id': [('type','=','other')]}
        return res

    def button_dummy(self, cr, uid, ids, context=None):
        return True

    def _prepare_voucher_line(self, cr, uid, account_move_line, type, checked, voucher, context):
        account_voucher_line_obj = self.pool.get('account.voucher.line')
        currency_pool = self.pool.get('res.currency')
        move_line_pool = self.pool.get('account.move.line')
        partner_pool = self.pool.get('res.partner')
        journal_pool = self.pool.get('account.journal')
        product_product_obj = self.pool.get('product.product')
        obj_currency_rate = self.pool.get('res.currency.rate')
        for aml in account_move_line:
            company_currency = aml.journal_id.company_id.currency_id.id
            currency_id = aml.currency_id.id or company_currency
            total_amount = 0
            line_currency_id = aml.currency_id and aml.currency_id.id or company_currency
            rs = {
                'name':aml.move_id.name,
                'type': type,
                'move_line_id':aml.id,
                'account_id':aml.account_id.id,
                'amount': 0.0,
                'date_original':aml.date,
                'date_due':aml.date_maturity,
                'currency_id': line_currency_id,
                'voucher_id': voucher.id,
            }

            avl = account_voucher_line_obj.create(cr, uid, rs, context)
            avl_id = account_voucher_line_obj.browse(cr, uid, avl, context=None)

            if checked:
                account_voucher_line_obj.write(cr, uid, [avl_id.id], {'amount': avl_id.amount_unreconciled,
                                                                      'reconcile': True})
                total_amount += avl_id.amount_unreconciled
        return total_amount


    def action_compute(self, cr, uid, ids, context=None):
        account_voucher_line_obj = self.pool.get('account.voucher.line')

        for voucher in self.browse(cr, uid, ids):
            line_ids = ids and account_voucher_line_obj.search(cr, uid, [('voucher_id', '=', voucher.id)]) or False
            if line_ids:
                account_voucher_line_obj.unlink(cr, uid, line_ids)

            if voucher.account_move_line_ids:
                total_amount = self._prepare_voucher_line(cr, uid, voucher.account_move_line_ids, 'cr', voucher.auto_fill_credit, voucher, context)
#             if voucher.other_move_line_db_ids:
#                 total_amount = self._prepare_voucher_line(cr, uid, voucher.other_move_line_db_ids, 'cr', voucher.auto_fill_other_credit, voucher, context)
            if voucher.move_line_cr_ids:
                total_amount = self._prepare_voucher_line(cr, uid, voucher.move_line_cr_ids, 'dr', voucher.auto_fill_debit, voucher, context)
#             if voucher.other_move_line_cr_ids:
#                 total_amount = self._prepare_voucher_line(cr, uid, voucher.other_move_line_cr_ids, 'dr', voucher.auto_fill_other_credit, voucher, context)
        return True

    def unrealized_gain_loss_get(self, cr, uid, voucher_id, line_total, move_id, name, company_currency, current_currency, context=None):
        currency_obj = self.pool.get('res.currency')
        move_line = {}

        voucher_brw = self.pool.get('account.voucher').browse(cr,uid,voucher_id,context)
        current_currency_obj = voucher_brw.currency_id or voucher_brw.journal_id.company_id.currency_id
        if not currency_obj.is_zero(cr, uid, current_currency_obj, line_total):
            diff = line_total
            account_id = False
            write_off_name = ''
            is_depo = False
            is_depo_main = False
            account_id = voucher_brw.company_id and voucher_brw.company_id.property_currency_gain_loss and voucher_brw.company_id.property_currency_gain_loss.id or False
            write_off_name = 'unrealized gain/loss - ' + name
#adding 10/17/2014
            
            sign = (diff > 0 and -1) or 1

#end adding 10/17/2014 ps and line 161
            move_line = {
                'name': write_off_name,
                'account_id': account_id,
                'move_id': move_id,
                'partner_id': voucher_brw.partner_id.id,
                'date': voucher_brw.date,
                'credit': diff > 0 and diff or 0.0,
                'debit': diff < 0 and -diff or 0.0,
                'amount_currency': False,
                'currency_id': False,
                'analytic_account_id': False,
                'is_depo': is_depo,
                'is_depo_main': is_depo_main,
                'exrate': 0.0
            }
#        raise osv.except_osv(_('Error'), _(str(move_line) + '---' + str('')))
        return move_line
    
    def writeoff_move_line_get(self, cr, uid, voucher_id, line_total, move_id, name, company_currency, current_currency, context=None):
        
        '''
        Set a dict to be use to create the writeoff move line.

        :param voucher_id: Id of voucher what we are creating account_move.
        :param line_total: Amount remaining to be allocated on lines.
        :param move_id: Id of account move where this line will be added.
        :param name: Description of account move line.
        :param company_currency: id of currency of the company to which the voucher belong
        :param current_currency: id of currency of the voucher
        :return: mapping between fieldname and value of account move line to create
        :rtype: dict
        '''
        currency_obj = self.pool.get('res.currency')
        move_line = {}

        voucher_brw = self.pool.get('account.voucher').browse(cr,uid,voucher_id,context)
        current_currency_obj = voucher_brw.currency_id or voucher_brw.journal_id.company_id.currency_id
        

        if not currency_obj.is_zero(cr, uid, current_currency_obj, line_total):
            diff = line_total
#             
#             raise osv.except_osv(_('Error'), _("applico"))
            if diff != 0 and voucher_brw.payment_option == 'none':
                if currency_obj.is_zero(cr, uid, current_currency_obj, voucher_brw.writeoff_amount):
                    return self.unrealized_gain_loss_get(cr, uid, voucher_id, line_total, move_id, name, company_currency, current_currency, context)
                else:
                    raise osv.except_osv(_('Error'), _("cannot process, please select the payment difference other than 'none'"))
            account_id = False
            write_off_name = ''
            is_depo = False
            is_depo_main = False
            account_id = voucher_brw.writeoff_acc_id.id
            acco_currency = voucher_brw.writeoff_acc_id and voucher_brw.writeoff_acc_id.currency_id and voucher_brw.writeoff_acc_id.currency_id.id or \
                             voucher_brw.journal_id.company_id.currency_id.id or False
            if current_currency_obj.id != acco_currency:
                raise osv.except_osv(_('Error'), _("pls select other write off account, the selected account currency, doesn't match with current payment currency."))
            if voucher_brw.payment_option == 'with_writeoff':
                write_off_name = 'other - ' + (voucher_brw.comment + ' (' + name + ')')
            elif voucher_brw.payment_option == 'without_writeoff':
                is_depo = True
                is_depo_main = True
                if voucher_brw.type == 'payment':
                    if diff > 0:
                        raise osv.except_osv(_('Error'), _("no negative value allowed for deposit amount"))
                elif voucher_brw.type == 'receipt':
                    if diff < 0:
                        raise osv.except_osv(_('Error'), _("no negative value allowed for deposit amount"))
                write_off_name = 'deposit - ' + name
#adding 10/17/2014
            
            sign = (diff > 0 and -1) or 1

#end adding 10/17/2014 ps and line 161
            move_line = {
                'name': write_off_name,
                'account_id': account_id,
                'move_id': move_id,
                'partner_id': voucher_brw.partner_id.id,
                'date': voucher_brw.date,
                'credit': diff > 0 and diff or 0.0,
                'debit': diff < 0 and -diff or 0.0,
                'amount_currency': company_currency <> current_currency and (sign * voucher_brw.writeoff_amount) or False,
                'currency_id': company_currency <> current_currency and current_currency or False,
                'analytic_account_id': voucher_brw.analytic_id and voucher_brw.analytic_id.id or False,
                'is_depo': is_depo,
                'is_depo_main': is_depo_main,
                'exrate': company_currency <> current_currency and ((voucher_brw.change_rate > 0) and voucher_brw.change_rate) or voucher_brw.ex_rate or 0.0
            }
#        raise osv.except_osv(_('Error'), _(str(move_line) + '---' + str('')))
        return move_line


    def bank_charge_account_create(self, cr, uid, voucher_id, move_id, company_currency, current_currency, name, context=None):
        '''
        Return a dict to be use to create the first account move line of given voucher.

        :param voucher_id: Id of voucher what we are creating account_move.
        :param move_id: Id of account move where this line will be added.
        :param company_currency: id of currency of the company to which the voucher belong
        :param current_currency: id of currency of the voucher
        :return: mapping between fieldname and value of account move line to create
        :rtype: dict
        '''
        move_line_pool = self.pool.get('account.move.line')
        voucher_brw = self.pool.get('account.voucher').browse(cr,uid,voucher_id,context)
        debit = credit = 0.0
        debit = voucher_brw.bank_charges_in_company_currency
        if debit < 0: credit = -debit; debit = 0.0
        if credit < 0: debit = -credit; credit = 0.0

        sign = debit - credit < 0 and -1 or 1
        #set the first line of the voucher
        bank_charge_acc =  voucher_brw.journal_id and voucher_brw.journal_id.property_bank_charges and voucher_brw.journal_id.property_bank_charges.id or False
        if not bank_charge_acc:
            raise osv.except_osv(_('No Bank Charges Account Found!'),_("You have to configure Bank Charges account on related journal!"))
        move_line1 = {
                'name': 'bank-charges ' + (name or ''),
                'debit': debit,
                'credit': credit,
                'account_id': bank_charge_acc,
                'move_id': move_id,
                'journal_id': voucher_brw.journal_id.id,
                'period_id': voucher_brw.period_id.id,
                'partner_id': voucher_brw.partner_id.id,
                'currency_id': company_currency <> current_currency and  current_currency or False,
                'amount_currency': company_currency <> current_currency and sign * voucher_brw.bank_charges_amount or 0.0,
                'date': voucher_brw.date,
                'exrate' : company_currency <> current_currency and ((voucher_brw.change_rate > 0) and voucher_brw.change_rate) or voucher_brw.ex_rate or 0.0,
            }

        move_line_pool.create(cr, uid, move_line1, context)
        move_line2 = {
                'name': 'bank-charges ' + (name or ''),
                'debit': credit,
                'credit': debit,
                'account_id': voucher_brw.account_id.id,
                'move_id': move_id,
                'journal_id': voucher_brw.journal_id.id,
                'period_id': voucher_brw.period_id.id,
                'partner_id': voucher_brw.partner_id.id,
                'currency_id': company_currency <> current_currency and  current_currency or False,
                'amount_currency': company_currency <> current_currency and -1 * sign * voucher_brw.bank_charges_amount or 0.0,
                'date': voucher_brw.date,
                'exrate' : company_currency <> current_currency and ((voucher_brw.change_rate > 0) and voucher_brw.change_rate) or voucher_brw.ex_rate or 0.0,
            }
        move_line_pool.create(cr, uid, move_line2, context)
        return True

    def voucher_move_line_create(self, cr, uid, voucher_id, line_total, move_id, company_currency, current_currency, context=None):
        '''
        Create one account move line, on the given account move, per voucher line where amount is not 0.0.
        It returns Tuple with tot_line what is total of difference between debit and credit and
        a list of lists with ids to be reconciled with this format (total_deb_cred,list_of_lists).

        :param voucher_id: Voucher id what we are working with
        :param line_total: Amount of the first line, which correspond to the amount we should totally split among all voucher lines.
        :param move_id: Account move wher those lines will be joined.
        :param company_currency: id of currency of the company to which the voucher belong
        :param current_currency: id of currency of the voucher
        :return: Tuple build as (remaining amount not allocated on voucher lines, list of account_move_line created in this method)
        :rtype: tuple(float, list of int)
        '''
        if context is None:
            context = {}
        move_line_obj = self.pool.get('account.move.line')
        currency_obj = self.pool.get('res.currency')
        tax_obj = self.pool.get('account.tax')
        tot_line = line_total

        rec_lst_ids = []

        date = self.read(cr, uid, voucher_id, ['date'], context=context)['date']
        ctx = context.copy()
        ctx.update({'date': date})
        voucher = self.pool.get('account.voucher').browse(cr, uid, voucher_id, context=ctx)
        voucher_currency = voucher.journal_id.currency or voucher.company_id.currency_id
        company_curr = self.pool.get('res.currency').browse(cr, uid, company_currency, context=None)
        prec = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')

        for line in voucher.line_ids:

            vc_exrate = ((voucher.change_rate > 0) and voucher.change_rate) or voucher.ex_rate
            exrate_line = ((line.change_rate > 0) and line.change_rate) or line.ex_rate
            move_line_exrate = line.move_line_id.exrate or self.pool.get('res.currency').browse(cr, uid, line.voucher_id.company_id.currency_id.id, context=context).rate
            if not line.amount and not (line.move_line_id and not float_compare(line.move_line_id.debit, line.move_line_id.credit, precision_digits=prec) and not float_compare(line.move_line_id.debit, 0.0, precision_digits=prec)):
                continue

            amount = self._rounding_voucher(cr, uid, line.inv_amount / vc_exrate * self.pool.get('res.currency').browse(cr, uid, line.voucher_id.company_id.currency_id.id, context=context).rate, \
                        line.currency_id.rounding, self.pool.get('decimal.precision').precision_get(cr, uid, 'Account'))


            if line.reconcile:
                amount = line.move_line_id.amount_residual
            currency_rate_difference = 0.0
            move_line = {
                'journal_id': voucher.journal_id.id,
                'period_id': voucher.period_id.id,
                'name': line.name or '/',
                'account_id': line.account_id.id,
                'move_id': move_id,
                'partner_id': voucher.partner_id.id,
                'currency_id': line.move_line_id and line.move_line_id.currency_id and (company_currency <> line.move_line_id.currency_id.id and line.move_line_id.currency_id.id) or False,
                'analytic_account_id': line.account_analytic_id and line.account_analytic_id.id or False,
                'quantity': 1,
                'credit': 0.0,
                'debit': 0.0,
                'date': voucher.date,
                'is_depo' : line.move_line_id.is_depo,
                'is_refund' : line.move_line_id.is_refund,
                'amount_currency' : False,
            }

            if (line.type=='dr'):
                tot_line += amount

                move_line['debit'] = amount
            else:
                tot_line -= amount

                move_line['credit'] = amount

            if voucher.tax_id and voucher.type in ('sale', 'purchase'):
                move_line.update({
                    'account_tax_id': voucher.tax_id.id,
                })

            if move_line.get('account_tax_id', False):
                tax_data = tax_obj.browse(cr, uid, [move_line['account_tax_id']], context=context)[0]
                if not (tax_data.base_code_id and tax_data.tax_code_id):
                    raise osv.except_osv(_('No Account Base Code and Account Tax Code!'),_("You have to configure account base code and account tax code on the '%s' tax!") % (tax_data.name))

            # compute the amount in foreign currency
            foreign_currency_diff = 0.0
            
            amount_currency = False
            sign = (move_line['debit'] - move_line['credit']) < 0 and -1 or 1
            if line.move_line_id:
#                 voucher_currency = voucher_brw.currency_id and voucher_brw.currency_id.id or voucher_brw.journal_id.company_id.currency_id.id
                # We want to set it on the account move line as soon as the original line had a foreign currency
                if line.move_line_id.currency_id and line.move_line_id.currency_id.id != company_currency:
                    # we compute the amount in that foreign currency.


                    move_line['exrate'] = move_line_exrate
                    if line.reconcile:
                        
                        amount_currency = sign * line.move_line_id.amount_residual_currency
                    else:
                        # otherwise we use the rates of the system (giving the voucher date in the context)

                        amount_currency = self._rounding_voucher(cr, uid, (move_line['debit']-move_line['credit']) / self.pool.get('res.currency').browse(cr, uid, line.voucher_id.company_id.currency_id.id, context=context).rate * move_line_exrate, line.move_line_id.currency_id.rounding, self.pool.get('decimal.precision').precision_get(cr, uid, 'Account'))
                    move_line['amount_currency'] = amount_currency
            voucher_line = move_line_obj.create(cr, uid, move_line)

            tot_line = self._rounding_voucher(cr, uid, tot_line, \
                        line.voucher_id.company_id.currency_id.rounding, self.pool.get('decimal.precision').precision_get(cr, uid, 'Account'))

            rec_ids = [voucher_line, line.move_line_id.id]

            inv_amountx = amount

            amountx = self._rounding_voucher(cr, uid, line.amount / vc_exrate * self.pool.get('res.currency').browse(cr, uid, line.voucher_id.company_id.currency_id.id, context=context).rate, \
                        line.voucher_id.company_id.currency_id.rounding, self.pool.get('decimal.precision').precision_get(cr, uid, 'Account'))

            gain_lost_amount = self._rounding_voucher(cr, uid, abs(inv_amountx - amountx), \
                        line.voucher_id.company_id.currency_id.rounding, self.pool.get('decimal.precision').precision_get(cr, uid, 'Account'))

            if not currency_obj.is_zero(cr, uid, voucher.company_id.currency_id, gain_lost_amount):
                gain_lost_acc = voucher.company_id and voucher.company_id.property_currency_gain_loss and voucher.company_id.property_currency_gain_loss.id or False 
                if not gain_lost_acc:
                    raise osv.except_osv(_('No Gain Lost Account Found!'),_("You have to configure gain/loss account on company profile!"))
                sign = (inv_amountx - amountx < 0 and -1) or 1
                debit_gain_loss = credit_gain_loss = 0.0
                if (line.type=='dr'):
                    if sign == -1:
                        debit_gain_loss = gain_lost_amount
                        tot_line += gain_lost_amount

                    else:
                        credit_gain_loss = gain_lost_amount

                        tot_line -= gain_lost_amount

                else:
                    if sign == -1:
                        credit_gain_loss = gain_lost_amount
                        tot_line -= gain_lost_amount
                    else:
                        debit_gain_loss = gain_lost_amount
                        tot_line += gain_lost_amount

                move_line1 = {
                    'journal_id': voucher.journal_id.id,
                    'period_id': voucher.period_id.id,
                    'name': (line.name and line.name + ' (exrate gain/loss)') or '/',
                    'account_id': gain_lost_acc,
                    'move_id': move_id,
                    'partner_id': voucher.partner_id.id,
                    'currency_id': False,
                    'analytic_account_id': line.account_analytic_id and line.account_analytic_id.id or False,
                    'quantity': 1,
                    'credit': credit_gain_loss,
                    'debit': debit_gain_loss,
                    'date': voucher.date,
                    'amount_currency': False,
                    'exrate': 0.0,
                    }

                move_line_obj.create(cr, uid, move_line1, context)
            if line.move_line_id.id:
                rec_lst_ids.append(rec_ids)
        tot_line = self._rounding_voucher(cr, uid, tot_line, \
                        company_curr.rounding, self.pool.get('decimal.precision').precision_get(cr, uid, 'Account'))
        return (tot_line, rec_lst_ids)

    def first_move_line_get(self, cr, uid, voucher_id, move_id, company_currency, current_currency, context=None):
        '''
        Return a dict to be use to create the first account move line of given voucher.

        :param voucher_id: Id of voucher what we are creating account_move.
        :param move_id: Id of account move where this line will be added.
        :param company_currency: id of currency of the company to which the voucher belong
        :param current_currency: id of currency of the voucher
        :return: mapping between fieldname and value of account move line to create
        :rtype: dict
        '''
        voucher = self.pool.get('account.voucher').browse(cr,uid,voucher_id,context)
        debit = credit = 0.0
        # TODO: is there any other alternative then the voucher type ??
        # ANSWER: We can have payment and receipt "In Advance".
        # TODO: Make this logic available.
        # -for sale, purchase we have but for the payment and receipt we do not have as based on the bank/cash journal we can not know its payment or receipt
        if voucher.type in ('purchase', 'payment'):
            credit = voucher.paid_amount_in_company_currency
        elif voucher.type in ('sale', 'receipt'):
            debit = voucher.paid_amount_in_company_currency

        if debit < 0: credit = -debit; debit = 0.0
        if credit < 0: debit = -credit; credit = 0.0
        sign = debit - credit < 0 and -1 or 1
        #set the first line of the voucher
        move_line = False
        if debit or credit:
            move_line = {
                    'name': voucher.name or '/',
                    'debit': round(debit,self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')),
                    'credit': round(credit,self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')),
                    'account_id': voucher.account_id.id,
                    'move_id': move_id,
                    'journal_id': voucher.journal_id.id,
                    'period_id': voucher.period_id.id,
                    'partner_id': voucher.partner_id.id,
                    'currency_id': company_currency <> current_currency and  current_currency or False,
                    'amount_currency': company_currency <> current_currency and sign * voucher.amount or 0.0,
                    'date': voucher.date,
                    'exrate' : company_currency <> current_currency and ((voucher.change_rate > 0) and voucher.change_rate) or voucher.ex_rate or 0.0,
                }

        return move_line

    def action_move_line_create(self, cr, uid, ids, context=None):
        '''
        Confirm the vouchers given in ids and create the journal entries for each of them
        '''
        if context is None:
            context = {}
        move_pool = self.pool.get('account.move')
        move_line_pool = self.pool.get('account.move.line')
        for voucher in self.browse(cr, uid, ids, context=context):
            local_context = dict(context, force_company=voucher.journal_id.company_id.id)
            if voucher.payment_option == 'none':
                if voucher.writeoff_amount < 0:
                    raise osv.except_osv(_('Error'), _('cannot process if the Different Amount In Negative Value'))
            no_data = True
            if voucher.line_ids:
                no_data = False

            if (voucher.grand_total <= 0) and no_data:
                raise osv.except_osv(_('Error'), _('cannot process, no transaction found.'))
            if voucher.move_id:
                continue
            company_currency = self._get_company_currency(cr, uid, voucher.id, context)
            current_currency = self._get_current_currency(cr, uid, voucher.id, context)
            # we select the context to use accordingly if it's a multicurrency case or not
            context = self._sel_context(cr, uid, voucher.id, context)
            # But for the operations made by _convert_amount, we always need to give the date in the context
            ctx = context.copy()
            ctx.update({'date': voucher.date})
            # Create the account move record.

            move_id = move_pool.create(cr, uid, self.account_move_get(cr, uid, voucher.id, context=context), context=context)
            # Get the name of the account_move just created
            name = move_pool.browse(cr, uid, move_id, context=context).name
            # Create the first line of the voucher
            first_move_line = self.first_move_line_get(cr,uid,voucher.id, move_id, company_currency, current_currency, local_context)

            line_total = 0.0

            if first_move_line:
                move_line_id = move_line_pool.create(cr, uid, first_move_line, local_context)
                move_line_brw = move_line_pool.browse(cr, uid, move_line_id, context=context)
                line_total = move_line_brw.debit - move_line_brw.credit

            if voucher.type == 'sale':
                line_total = line_total - self._convert_amount(cr, uid, voucher.tax_amount, voucher.id, context=ctx)
            elif voucher.type == 'purchase':
                line_total = line_total + self._convert_amount(cr, uid, voucher.tax_amount, voucher.id, context=ctx)
            # Create one move line per voucher line where amount is not 0.0

            line_total, rec_list_ids = self.voucher_move_line_create(cr, uid, voucher.id, line_total, move_id, company_currency, current_currency, context)
            
            # Create the writeoff line if needed

            
            ml_writeoff = self.writeoff_move_line_get(cr, uid, voucher.id, line_total, move_id, name, company_currency, current_currency, local_context)


            if ml_writeoff:
                move_line_pool.create(cr, uid, ml_writeoff, local_context)
            # We post the voucher.
            self.write(cr, uid, [voucher.id], {
                'move_id': move_id,
                'state': 'posted',
                'number': name,
            })

            if voucher.bank_charges_amount != 0:
                self.bank_charge_account_create(cr,uid,voucher.id, move_id, company_currency, current_currency, name, context)

            if voucher.journal_id.entry_posted:
                move_pool.post(cr, uid, [move_id], context={})
            # We automatically reconcile the account move lines.
            reconcile = False
            for rec_ids in rec_list_ids:
                if len(rec_ids) >= 2:
                    reconcile = move_line_pool.reconcile_partial(cr, uid, rec_ids, writeoff_acc_id=voucher.writeoff_acc_id.id, writeoff_period_id=voucher.period_id.id, writeoff_journal_id=voucher.journal_id.id)
        return True



    _columns = {
        'grand_total':fields.function(_get_grand_total, digits_compute=dp.get_precision('Account'), string='Grand Total', type='float', readonly=True),
        'ex_rate': fields.function(_rate, type='float', digits=(12,6), string='Currency Rate'),
        'bank_charges_amount': fields.float('Bank Charges', digits_compute=dp.get_precision('Account'), readonly=True, states={'draft':[('readonly',False)]}),
        'auto_fill_debit': fields.boolean('Auto Fill Debit', readonly=True, states={'draft':[('readonly',False)]}, help="Tick if you want to auto full fill for all selected invoices."),
        'auto_fill_credit': fields.boolean('Auto Fill Credit', readonly=True, states={'draft':[('readonly',False)]}, help="Tick if you want to auto full fill for all selected invoices."),
        'account_move_line_ids':fields.many2many('account.move.line', 'voucher_move_line_rel', 'voucher_id', 'line_id', 'Move Line Debit'),
        'move_line_cr_ids':fields.many2many('account.move.line', 'voucher_move_line_cr_rel', 'voucher_id', 'line_id', 'Move Line Credit'),
        'cheque_no': fields.char('Cheque No', size=64, readonly=True, states={'draft':[('readonly',False)]}, help="Transaction Cheque No."),
        'bank_draft_no': fields.char('Bank Draft No', size=64, readonly=True, states={'draft':[('readonly',False)]}, help="Transaction Bank Draft No."),
        'payment_option':fields.selection([
                       ('none', 'None'),
                       ('without_writeoff', 'Deposit Amount'),
                       ('with_writeoff', 'Reconcile Payment Balance')
                       ], 'Payment Difference', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="This field helps you to choose what you want to do with the eventual difference between the paid amount and the sum of allocated amounts. You can either choose to keep open this difference on the partner's account, or reconcile it with the payment(s) or use as deposit amount."),
        'bank_charges_in_company_currency': fields.function(_bank_charges_in_company_currency, digits_compute=dp.get_precision('Account'), string='Bank Charges in Company Currency', type='float', readonly=True),
        'paid_amount_in_company_currency': fields.function(_paid_amount_in_company_currency, string='Paid Amount in Company Currency', type='float', readonly=True),
        'change_rate': fields.float('Change Rate', digits=(12,6), help='Change Currency Rate', readonly=True, states={'draft':[('readonly',False)]}),
        'total_in_home_currency': fields.function(_total_in_home_currency, digits_compute=dp.get_precision('Account'), string='Total In Home Currency', type='float', readonly=True),
        'total_payment_amount' : fields.function(_get_pay_amount, digits_compute=dp.get_precision('Account'), string='Total Receipt Amount', type='float', readonly=True),
        'writeoff_amount' : fields.function(_get_writeoff_amount, digits_compute=dp.get_precision('Account'), string='Difference Amount', type='float', readonly=True, help="Computed as the difference between the amount stated in the voucher and the sum of allocation on the voucher lines."),
     }

    _defaults = {
        'payment_option': 'none',
    }

account_voucher()

class account_voucher_line(osv.osv):

    _inherit = 'account.voucher.line'

    def _rounding_voucher(self, cr, uid, total_amount, voucher_currency_rounding, decimal_prec_acc, context=None):
        total_amount = float_round(total_amount, precision_rounding=voucher_currency_rounding)
        total_amount = round(total_amount,decimal_prec_acc)

        return total_amount

    def _compute_balance2(self, cr, uid, ids, name, args, context=None):
        currency_pool = self.pool.get('res.currency')
        product_product_obj = self.pool.get('product.product')
        rs_data = {}
        deci_prec_acc = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')
        for line in self.browse(cr, uid, ids, context=context):
            rs_data[line.id] = self.get_balance(cr, uid, line.voucher_id.journal_id.id, line.voucher_id.date, line.voucher_id.change_rate, line.move_line_id.id, line.currency_id.id, line.change_rate, line.reconcile, line.amount, context)
        return rs_data

    def _qty_balance_amount(self, cr, uid, ids, name, arg, context=None):
        if not ids: return {}
        res = {}
        for obj in self.browse(cr, uid, ids, context=context):
            res[obj.id] = obj.amount_unreconciled - obj.amount
        return res

    def _amount_home(self, cr, uid, ids, name, args, context=None):
        if not ids: return {}
        res = {}
        voucher_rate = company_currency_rate = 1.0
        for line in self.browse(cr, uid, ids, context=context):
            company_currency = line.voucher_id and line.voucher_id.company_id and line.voucher_id.company_id.currency_id or False
            voucher_currency = line.voucher_id and line.voucher_id.journal_id and line.voucher_id.journal_id.currency or company_currency or False
            if voucher_currency.id == company_currency.id:
                res[line.id] = line.amount
            else:
                ctx = {'date':line.voucher_id.date}
                voucher_rate = ((line.change_rate > 0) and line.change_rate) or line.voucher_id.ex_rate
                company_rate = self.pool.get('res.currency').browse(cr, uid, company_currency.id, context=ctx).rate
                res[line.id] = self._rounding_voucher(cr, uid, line.amount / voucher_rate * company_rate, voucher_currency.rounding, self.pool.get('decimal.precision').precision_get(cr, uid, 'Account'))
                 
        return res

    def _amount_inv_home(self, cr, uid, ids, name, args, context=None):
        if not ids: return {}
        res = {}
        for line in self.browse(cr, uid, ids, context=context):
            company_currency = line.voucher_id and line.voucher_id.company_id and line.voucher_id.company_id.currency_id or False
            voucher_currency = line.voucher_id and line.voucher_id.journal_id and line.voucher_id.journal_id.currency or company_currency or False
            if voucher_currency.id == company_currency.id:
                res[line.id] = line.amount
            else:
                ctx = {'date':line.move_line_id and line.move_line_id.date}
                voucher_rate = ((line.voucher_id.change_rate > 0) and line.voucher_id.change_rate) or self.pool.get('res.currency').browse(cr, uid, voucher_currency.id, context=ctx).rate
                company_rate = self.pool.get('res.currency').browse(cr, uid, company_currency.id, context=ctx).rate
                res[line.id] = self._rounding_voucher(cr, uid, line.amount / voucher_rate * company_rate, voucher_currency.rounding, self.pool.get('decimal.precision').precision_get(cr, uid, 'Account'))
 
        return res

    def get_exrate(self, cr, uid, current_currency, cur_date, context=None):
        res_currency_rate_obj = self.pool.get("res.currency.rate")
        if current_currency and cur_date:
            res_currency_rate_ids = res_currency_rate_obj.search(cr, uid, [('currency_id', '=', current_currency), ('name', '<=', cur_date)], order='name DESC', limit=1)
            if res_currency_rate_ids:
                return res_currency_rate_obj.browse(cr, uid, res_currency_rate_ids[0], context=context).rate
            else:
                return 0
        else:
            return 0
        
    def _rate(self, cr, uid, ids, name, arg, context=None):
        if not ids: return {}
        res = {}
        res_currency_rate_obj = self.pool.get("res.currency.rate")

        for obj in self.browse(cr, uid, ids, context=context):
            current_currency = obj.currency_id and obj.currency_id.id
            cur_date = obj.voucher_id.date or False
            res[obj.id] = self.get_exrate(cr, uid, current_currency, cur_date, context)
        return res



    def get_balance(self, cr, uid, parent_journal_id, parent_date, parent_change_rate, move_line_id, line_currency_id, change_rate, reconcile, amount, context=None):
        vals = {}
        deci_prec_acc = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')
        amount_inv_unreconciled = amount_original = amount_unreconciled = inv_amount = current_amount = 0.0
        aml_obj = self.pool.get("account.move.line")
        aj_obj = self.pool.get("account.journal")
        currency_pool = self.pool.get("res.currency")
        if not (move_line_id or parent_journal_id):
            return vals

        ctx = context.copy()
        ctx.update({'date': parent_date})
        ctx2 = context.copy()
        move_line = aml_obj.browse(cr, uid, move_line_id, context=context)
        journal = aj_obj.browse(cr, uid, parent_journal_id, context=context)
        ctx2.update({'date': move_line and move_line.date})
        company_currency = journal.company_id.currency_id.id
        voucher_currency = (journal.currency and journal.currency.id) or company_currency
        voucher_currency_rounding = currency_pool.browse(cr, uid, voucher_currency, context=False).rounding
        rate_home = currency_pool.browse(cr, uid, company_currency, context=ctx).rate
        rate_inv = move_line.exrate or rate_home
        rate_now = ((change_rate > 0) and change_rate) or currency_pool.browse(cr, uid, line_currency_id, context=ctx).rate
        rate_payment = ((parent_change_rate > 0) and parent_change_rate) or currency_pool.browse(cr, uid, voucher_currency, context=ctx).rate
        if move_line.currency_id:

#             amount_invoice = self._rounding_voucher(cr, uid, abs(move_line.amount_currency) / (rate_inv/rate_home) / (rate_home/rate_payment), voucher_currency_rounding, deci_prec_acc)
#             if move_line.currency_id.id == voucher_currency:
#                 amount_original = abs(move_line.amount_currency)
#                 amount_unreconciled = abs(move_line.amount_residual_currency)
#             else:
#                 amount_original = self._rounding_voucher(cr, uid, abs(move_line.amount_currency) / (rate_now/rate_home) / (rate_home/rate_payment), voucher_currency_rounding, deci_prec_acc)
#                 amount_unreconciled = self._rounding_voucher(cr, uid, abs(move_line.amount_residual_currency) / (rate_now/rate_home) / (rate_home/rate_payment), voucher_currency_rounding, deci_prec_acc)


            amount_original = self._rounding_voucher(cr, uid, \
                                                     (abs(move_line.amount_currency) * rate_home / rate_now) * rate_payment / rate_home \
                                                     , voucher_currency_rounding, deci_prec_acc)
            amount_unreconciled = self._rounding_voucher(cr, uid, \
                                                         (abs(move_line.amount_residual_currency) * rate_home / rate_now) * rate_payment / rate_home \
                                                         , voucher_currency_rounding, deci_prec_acc)

            vals['amount_org'] = abs(move_line.amount_currency)
            vals['amount_original'] = amount_original
            vals['amount_unreconciled'] = amount_unreconciled
#             vals['amount_invoice'] = amount_invoice

#             if voucher_currency == company_currency:
#                 amount_inv_unreconciled = abs(move_line.amount_residual)
#             else:
# 
#                 if voucher_currency == move_line.currency_id.id:
#                     amount_inv_unreconciled = abs(move_line.amount_residual_currency)
#                 else:
#                     amount_inv_unreconciled = self._rounding_voucher(cr, uid, abs(move_line.amount_residual) * (rate_payment/rate_home), voucher_currency_rounding, deci_prec_acc)
            if reconcile:
                vals['amount'] = amount_unreconciled
                amount = amount_unreconciled
            if amount > amount_unreconciled:
                vals['reconcile'] = True
                vals['amount'] = amount_unreconciled
                amount = amount_unreconciled

    
            inv_amount = (abs(amount) * rate_home / rate_payment) * rate_now / rate_home
            inv_amount = (inv_amount * rate_home / rate_inv) * rate_payment / rate_home 
            inv_amount = self._rounding_voucher(cr, uid, inv_amount, voucher_currency_rounding, deci_prec_acc)
#             vals['amount_inv_unreconciled'] = amount_inv_unreconciled
#             vals['gain_loss'] = amount_inv_unreconciled - amount_unreconciled
            vals['inv_amount'] = inv_amount
            vals['gain_loss_amount'] = inv_amount - amount


        else:
            if company_currency == voucher_currency:
#                 amount_invoice = abs(move_line.debit - move_line.credit)
#                 amount_inv_unreconciled = abs(move_line.amount_residual)
                amount_original = abs(move_line.debit - move_line.credit)
                amount_unreconciled = abs(move_line.amount_residual)
                if reconcile:
                    vals['amount'] = amount_unreconciled
                    amount = amount_unreconciled
                if amount > amount_unreconciled:
                    vals['reconcile'] = True
                    vals['amount'] = amount_unreconciled
                    amount = amount_unreconciled
                inv_amount = (abs(amount) * rate_home / rate_payment) * rate_now / rate_home
                inv_amount = (inv_amount * rate_home / rate_inv) * rate_payment / rate_home
                
                inv_amount = self._rounding_voucher(cr, uid, inv_amount, voucher_currency_rounding, deci_prec_acc)
            else:

                amount_original = self._rounding_voucher(cr, uid, \
                                                         abs(move_line.debit - move_line.credit) * rate_payment / rate_home \
                                                         , voucher_currency_rounding, deci_prec_acc)
                amount_unreconciled = self._rounding_voucher(cr, uid, \
                                                         abs(move_line.amount_residual) * rate_payment / rate_home \
                                                         , voucher_currency_rounding, deci_prec_acc)

#                 amount_invoice = self._rounding_voucher(cr, uid, currency_pool.compute(cr, uid, company_currency, voucher_currency, abs(move_line.debit - move_line.credit), context=ctx), voucher_currency_rounding, deci_prec_acc)
#                 amount_inv_unreconciled = self._rounding_voucher(cr, uid, currency_pool.compute(cr, uid, company_currency, voucher_currency, abs(move_line.amount_residual), context=ctx), voucher_currency_rounding, deci_prec_acc)


                current_amount = amount * (rate_home/ rate_payment) * (rate_now/ rate_home)

                if reconcile:
                    vals['amount'] = amount_unreconciled
                    amount = amount_unreconciled
                if amount > amount_unreconciled:
                    vals['reconcile'] = True
                    reconcile = True
                    vals['amount'] = amount_unreconciled
                    amount = amount_unreconciled

                inv_amount = (abs(amount) * rate_home / rate_payment) * rate_now / rate_home
                inv_amount = (inv_amount * rate_home / rate_inv) * rate_payment / rate_home
                
                inv_amount = self._rounding_voucher(cr, uid, inv_amount, voucher_currency_rounding, deci_prec_acc)
#                 if reconcile:
#                     inv_amount = amount_inv_unreconciled
#                 else:
#                     inv_amount = self._rounding_voucher(cr, uid, (rate_payment/ rate_home) / (rate_inv/rate_home) * current_amount, voucher_currency_rounding, deci_prec_acc)




            vals['amount_org'] = abs(move_line.debit - move_line.credit)
            vals['amount_original'] = amount_original
            vals['amount_unreconciled'] = amount_unreconciled
#             vals['amount_invoice'] = amount_invoice
#             vals['amount_inv_unreconciled'] = amount_inv_unreconciled
#             vals['gain_loss'] = amount_inv_unreconciled - amount_unreconciled
            vals['inv_amount'] = inv_amount
            vals['gain_loss_amount'] = inv_amount - amount

        return vals

    def onchange_change_rate(self, cr, uid, ids, parent_journal_id, parent_date, parent_change_rate, move_line_id, line_currency_id, change_rate, reconcile, amount, context=None):
        vals = self.get_balance(cr, uid, parent_journal_id, parent_date, parent_change_rate, move_line_id, line_currency_id, change_rate, reconcile, amount, context)
        return {'value': vals}

    def onchange_reconcile(self, cr, uid, ids, parent_journal_id, parent_date, parent_change_rate, move_line_id, line_currency_id, change_rate, reconcile, amount, amount_unreconciled, context=None):   
        if reconcile:
            amount = amount_unreconciled
            vals = self.get_balance(cr, uid, parent_journal_id, parent_date, parent_change_rate, move_line_id, line_currency_id, change_rate, reconcile, amount, context)
            vals['balance_amount'] = vals['amount_unreconciled'] - amount
        else:
            amount = 0
            vals = self.get_balance(cr, uid, parent_journal_id, parent_date, parent_change_rate, move_line_id, line_currency_id, change_rate, reconcile, amount, context)
            vals['balance_amount'] = vals['amount_unreconciled'] - amount
            vals['amount'] = 0
            


        return {'value': vals}

    def onchange_amount(self, cr, uid, ids, parent_journal_id, parent_date, parent_change_rate, move_line_id, line_currency_id, change_rate, reconcile, amount, amount_unreconciled, context=None):
        vals = {}
        
        if amount:
            if amount > amount_unreconciled:
                amount = amount_unreconciled
            reconcile = (amount == amount_unreconciled)
            vals = self.get_balance(cr, uid, parent_journal_id, parent_date, parent_change_rate, move_line_id, line_currency_id, change_rate, reconcile, amount, context)
            vals['reconcile'] = (amount == amount_unreconciled)
            vals['balance_amount'] = vals['amount_unreconciled'] - amount
        return {'value': vals}

    _columns = {
        'change_rate': fields.float('Change Rate', digits=(12,6), help='Change Currency Rate'),
        'ex_rate': fields.function(_rate, type='float', digits=(12,6), string='Currency Rate'),
        'amount_org': fields.function(_compute_balance2, multi='dc', type='float', string='Original Amount', digits_compute=dp.get_precision('Account')),
        'amount_original': fields.function(_compute_balance2, multi='dc', type='float', string='Original Amount', store=True, digits_compute=dp.get_precision('Account')),
        'amount_unreconciled': fields.function(_compute_balance2, multi='dc', type='float', string='Open Balance', store=True, digits_compute=dp.get_precision('Account')),
        'amount_invoice': fields.function(_compute_balance2, multi='dc', type='float', string='Invoice Amount', store=True, digits_compute=dp.get_precision('Account')),
        'amount_inv_unreconciled': fields.function(_compute_balance2, multi='dc', type='float', string='Inv Open Balance', store=True, digits_compute=dp.get_precision('Account')),
        'gain_loss': fields.function(_compute_balance2, multi='dc', type='float', string='Gain/Loss', store=True, digits_compute=dp.get_precision('Account')),
        'inv_amount': fields.function(_compute_balance2, multi='dc', type='float', string='Inv Amount', digits_compute=dp.get_precision('Account'), store=True),
        'gain_loss_amount': fields.function(_compute_balance2, multi='dc', type='float', string='Gain/Loss Amount', digits_compute=dp.get_precision('Account'), store=True),
        'balance_amount': fields.function(_qty_balance_amount, type='float', string='Balance Amount', digits_compute=dp.get_precision('Account')),
        'amount_home': fields.function(_amount_home, digits_compute=dp.get_precision('Account'), string='Amount Home', type='float', readonly=True),
        'amount_inv_home': fields.function(_amount_inv_home, digits_compute=dp.get_precision('Account'), string='Amount Inv Home', type='float', readonly=True),
    }

account_voucher_line()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
